package worker

import (
	"svvenus/util/uttime"
	"time"
)

// 服务器定时触发器

type ScheduleType int //服务器触发器类型

const (
	PerSecond        ScheduleType = iota //每秒
	PerSecond10                          //每10秒
	PerMinute                            //每分
	PerHour                              //每小时
	OClock                               //整点
	OClock0                              //整0点
	OClock5                              //整5点
	OClock6                              //整6点
	BeginSunday                          //每周日0点
	BeginMonday                          //每周一0点
	BeginMonth                           //每月初
	ServeTrigTypeMax                     //结束
)

var (
	ScheduleMain  func()                            //服务器内部循环
	ScheduleChan  = make(chan func(), 256)          //队列
	ScheduleBinds = make(map[ScheduleType][]func()) //触发列表

)

// ScheduleWorker
// @Description: 服务器触发器
type ScheduleWorker struct {
	tSchedule time.Time //上次触发时间

	tPerSecond   time.Time
	tPerSecond10 time.Time
	tPerMinute   time.Time
	tPerHour     time.Time
	tOClock      time.Time
	tOClock0     time.Time
	tOClock5     time.Time
	tOClock6     time.Time
	tBeginSunday time.Time
	tBeginMonday time.Time
	tBeginMonth  time.Time
}

// NewScheduleWorker 创建
// @return *ScheduleWorker
func NewScheduleWorker() *ScheduleWorker {
	dt := time.Now()
	sv := &ScheduleWorker{}
	sv.tSchedule = dt
	sv.tPerSecond = dt.Add(time.Second)
	sv.tPerSecond10 = dt.Add(time.Second * 10)
	sv.tPerMinute = dt.Add(time.Minute)
	sv.tPerHour = dt.Add(time.Hour)
	sv.tOClock = dt
	sv.tOClock0 = dt
	sv.tOClock5 = dt
	sv.tOClock6 = dt
	sv.tBeginSunday = dt
	sv.tBeginMonday = dt
	sv.tBeginMonth = dt
	for i := PerSecond; i < ServeTrigTypeMax; i++ {
		v := make([]func(), 0)
		ScheduleBinds[i] = v
	}
	return sv
}

// Start 启动
// @receiver w
// @param fnRegister
func (w *ScheduleWorker) Start(fnRegister func()) {
	fnRegister()
	for {
		w.Loop()

		//不同服务器的内部循环
		if ScheduleMain != nil {
			ScheduleChan <- ScheduleMain
		}

		time.Sleep(time.Millisecond * 100)
	}
}

// ScheduleWorkerMainSet 添加主循环
// @param fn
func ScheduleWorkerMainSet(fn func()) {
	ScheduleMain = fn
}

// ScheduleWorkerBind 绑定
// @param t
// @param fn
func ScheduleWorkerBind(t ScheduleType, fn func()) {
	ScheduleBinds[t] = append(ScheduleBinds[t], fn)
}

// Loop 触发判断
// @receiver w
// @param dt
func (w *ScheduleWorker) Loop() {
	dt := time.Now()
	w.tSchedule = dt

	if dt.After(w.tPerSecond) {
		for _, s := range ScheduleBinds[PerSecond] {
			ScheduleChan <- s
		}
		w.tPerSecond = dt.Add(time.Second)
	}
	if dt.After(w.tPerSecond10) {
		for _, s := range ScheduleBinds[PerSecond10] {
			ScheduleChan <- s
		}
		w.tPerSecond10 = dt.Add(time.Second * 10)
	}
	if dt.After(w.tPerMinute) {
		for _, s := range ScheduleBinds[PerMinute] {
			ScheduleChan <- s
		}
		w.tPerMinute = dt.Add(time.Minute)
	}
	if dt.After(w.tPerHour) {
		for _, s := range ScheduleBinds[PerHour] {
			ScheduleChan <- s
		}
		w.tPerHour = dt.Add(time.Hour)
	}
	if !uttime.SameHour(dt, w.tOClock) {
		for _, s := range ScheduleBinds[OClock] {
			ScheduleChan <- s
		}
		w.tOClock = dt
	}
	if !uttime.SameHour(dt, w.tOClock0) && dt.Hour() == 0 {
		for _, s := range ScheduleBinds[OClock0] {
			ScheduleChan <- s
		}
		w.tOClock0 = dt
	}
	if !uttime.SameHour(dt, w.tOClock5) && dt.Hour() == 5 {
		for _, s := range ScheduleBinds[OClock5] {
			ScheduleChan <- s
		}
		w.tOClock5 = dt
	}
	if !uttime.SameHour(dt, w.tOClock6) && dt.Hour() == 6 {
		for _, s := range ScheduleBinds[OClock6] {
			ScheduleChan <- s
		}
		w.tOClock6 = dt
	}
	//todo 判断触发 待实现
}

// ScheduleExec
// @Description:
// @param schedule
func ScheduleExec(schedule func()) {
	schedule()
}
